<?php
/***************************************************************************
#                       数据库操作类[继承自db抽象类]
# 封装数据库的 增 删 改 查
# 构造函数 => 接受参数设置($host,$user,$pwd,$dbName)以及
#             配置文件: HOST USERNAME PASSWORD DBNAME
#       说明: 如果配置文件正确或参数传输正确，则初始化对象成功则连入数据库
#    		  初始化对象但是参数有误，则可以用connect($host,$user,$pwd)重连
# 公共方法介绍 ： 
#   数据库的重连:                      connect($host,$user,$pwd)   
#   返回数据库链接资源：               get_handle()
#   切换数据库并选择返回字符集；       change_db ($dbName,$charset='')
#   发送Query查询:                     auery ($sql)
#
#   增 (通过关联数组插入数据)          arrInsert($tableName,$Arr)
#	删 (通过关联数组确定where条件)     arrDel($tableName,$Arr)
# 	改 (通过关联数组……)                arrUpdate ($tableName,$Newdat,$Wdat)
#   查 (返回二维关联数组)			   getAll($sql)
#   
# 	
#
***************************************************************************/
// require 'Log.class.php';
class MySQL {
	private static $host ;
	private static $user ;
	private static $pwd ;
	private static $dbName;
	private static $dblink = NULL;
	public $charSet = 'utf8';
	# 单列模式
	protected static $ins =  null;
	final protected function __construct(){
		// 读取配置文件
		defined('HOST')     ? self::$host    = HOST     :0 ;
		defined('USERNAME') ? self::$user    = USERNAME :0 ;
		defined('PASSWORD') ? self::$pwd     = PASSWORD :0 ;
		defined('DBNAME')   ? self::$dbName  = DBNAME   :'' ;

		// // 链接数据库
		self::connect(self::$host,self::$user,self::$pwd);
		if (self::$dbName != '')  $this->change_db(self::$dbName);
	}

	public static function init($host ='',$user = '',$pwd = '',$dbName=''){
		// 读取构造参数
		if (isset($host)   && ($host   != '')) self::$host   = $host;
		if (isset($user)   && ($user   != '')) self::$user   = $user;
		if (isset($pwd)    && ($pwd    != '')) self::$pwd    = $pwd ;
		if (isset($dbName) && ($dbName != '')) self::$dbName = $dbName;

		if (self::$ins instanceof self) {
			return self::$ins;
		}else{
			self::$ins = new self();
			return self::$ins;
		}
	}
	// 防止克隆对象
	final protected function __clone(){
		return false;
	}

	// 如果初始化链接失败 可以修改参数链接数据库
	public function connect($host='',$user='',$pwd=''){
		if (isset($host)   && ($host   != '')) self::$host   = $host;
		if (isset($user)   && ($user   != '')) self::$user   = $user;
		if (isset($pwd)    && ($pwd    != '')) self::$pwd    = $pwd ;
	
		// 链接数据库
		$l = @mysql_connect(self::$host,self::$user,self::$pwd); 
		# 记录异常日志
		if (!$l) Log::write('Could not connect to MySQL: ' . mysql_error());  
		else     self::$dblink = $l;
	}

	// 发送Query 查询
	public function query ($sql){
		$Q = mysql_query($sql,self::$dblink);
		Log::write($sql);    # 记录sql语句 
		if ($Q)	return $Q;
		else	return false;
	}
	
	// 返回数据库链接句柄
	public function get_handle(){
		return self::$dblink;
	}
	
	// 选择（切换）数据库
	public function change_db ($dbName,$charset=''){
		if ($dbName != '') self::$dbName = $dbName;
		if ($charset != '') $this->charSet = $charset;	
		// 选择数据库
		$sql = 'USE '.self::$dbName;
		$this->query($sql);
		// 设置字符集
		$sql = 'SET NAMES '.$this->charSet;
		$this->query($sql);
	}

	private function Iinto ($tableName,$Arr){
		$insert_sql = 'INSERT INTO '.$tableName.'(';
		foreach ($Arr as $name => $value ) $insert_sql .= $name .',';
		// 去除最后一个字符
		$insert_sql = substr($insert_sql, 0,-1);
		$insert_sql .= ') values(';
		foreach ($Arr as $name => $value ){
			if (is_string($value)) $insert_sql .= '"'.$value . '"' .',';
			else				   $insert_sql .=     $value .',';
		}
		// 去除最后一个字符
		$insert_sql = substr($insert_sql, 0,-1);
		$insert_sql .= ');';
		
		return $this->Query($insert_sql);
	}

	// 通过关联数组插入数据
	public function arrInsert ($tableName,$Arr){
		// 判断$Arr 是否二维数组
		if(is_array($Arr)){
			foreach ($Arr as $k => $v) {
				if (is_array($Arr[$k])) {
					$Is2=2;
					break;
				} 
				else{ 
					$Is2 = 1;
					break ;
				}
			}
		}else $Is2 = 0;

		if (2==$Is2) {
			foreach ($Arr as $key => $value)
				$this->Iinto($tableName,$Arr[$key])? $isOk=true :$isOk=false;	
		}
		else if (1==$Is2)	$this->Iinto($tableName,$Arr)?$isOk=true :$isOk=false;
		else if (0==$Is2)   $isOk = false;

		return $isOk;
	}

	
	// 通过关联数组 删除数据
	public function arrDel($tableName,$Arr){
		// 如果数组为空 则为非法输入
		if (empty($Arr)) {
			return false;
		}
		$delsql = 'DELETE FROM '.$tableName.' WHERE ';
		foreach ($Arr as $key => $value) {
			// 如果数组并非索引数组 既为非法输入
			if (!is_string($key)) return false;
			if (is_string($value)) $delsql .= $key.'="'.$value.'"';  
			else 				   $delsql .= $key.'=' .$value;
			$delsql .= ' AND ';
		}
		$delsql = substr($delsql, 0, -5);
		// echo $delsql;
		return $this->Query($delsql);
	}

	// 通过两个关联数组 修改数据
	public function arrUpdate ($tableName,$Newdat,$Wdat){
		# "UPDATE tablees SET  WHERE "
		// 如果数组为空 则为非法输入
		if (empty($Wdat)) {
			return false;
		}
		$Csql= 'UPDATE '.$tableName.' SET ';

		foreach ($Newdat as $key => $value) {
			if (is_string($value)) $Csql .= $key.'="'.$value.'"';  
			else 				   $Csql .= $key.'=' .$value;
			$Csql .=',';
		}
		$Csql = substr($Csql, 0,-1);
		$Csql .= ' WHERE ';
		
		foreach ($Wdat as $k => $v) {
			if (!is_string($key)) return false;    #防止(where 1)修改所有数据
			if (is_string($value)) $Csql .= $k.'="'.$v.'"';  
			else 				   $Csql .= $k.'=' .$v;
			$Csql .=' AND ';
		}
		$Csql = substr($Csql, 0,-5);
		return $this->Query($Csql);

	}

	// 查询返回关联数组
	public function getAll($sql){
		$arr = array();
		$res = $this->Query($sql);
		while ($row = mysql_fetch_assoc($res)) $arr[] =$row;
		return $arr; 
	}
	// 返回单个值
	public function getOne ($sql){
		$res = $this->Query($sql);
		$rs = mysql_fetch_row($res);
		return $rs[0];
	}
	// 查询数据库中数据的条数
	public function getCount($tableName,$arrDat=''){
		$sql = 'SELECT COUNT(*) FROM '.$tableName.' WHERE ';
		if (!$arrDat == ''){
			foreach ($arrDat as $key => $value) {
			// 如果数组并非索引数组 既为非法输入
				if (!is_string($key)) return false;
				if (is_string($value)) $sql .= $key.'="'.$value.'"';  
				else 				   $sql .= $key.'=' .$value;
				$sql .= ' AND ';
			}
			$sql = substr($sql, 0, -5);
		}else{
			$sql .='1';
		}
		
		$res = $this->Query($sql);
		$rs = mysql_fetch_row($res);
		return $rs[0];
	}


	// 关闭资源
	public function close(){
		return mysql_close($this->dblink);
	}

}